package com.karson.front.service.Impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.karson.common.constants.SmsConstants;
import com.karson.common.exception.AsmrException;
import com.karson.common.exception.ExceptionCodeEnum;
import com.karson.common.model.User;
import com.karson.common.request.LoginMobileRequest;
import com.karson.common.request.LoginRequest;
import com.karson.common.response.LoginResponse;
import com.karson.common.util.AsmrUtil;
import com.karson.common.util.DateUtil;
import com.karson.common.util.SercretUtil;
import com.karson.common.vo.UserVo;
import com.karson.front.service.LoginService;
import com.karson.front.service.SmsService;
import com.karson.service.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.Random;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private UserService userService;
    @Autowired
    private SmsService  smsService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getAccount, loginRequest.getAccount());
        User user = userService.getOne(userQueryWrapper);
        if (ObjectUtil.isNull(user)) {
            throw new AsmrException("账号未注册");
        }
        if (!user.getStatus()){
            throw new  AsmrException("账号被封禁了");
        }
        // 校验密码
        String password = SercretUtil.encryptPassword(loginRequest.getPwd(), loginRequest.getAccount());
        if (!user.getPwd().equals(password)) {
            throw new AsmrException("密码错误");
        }
        // 可以指定`账号id`和`设备类型`进行登录  StpUtil.login(10001, "PC");   TODO
        StpUtil.login(user.getUid());
        // 第2步，获取 Token  相关参数
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        LoginResponse loginResponse = new LoginResponse();
        loginResponse.setUid(user.getUid());
        loginResponse.setNikeName(user.getNickname());
        loginResponse.setPhone(user.getPhone());
        loginResponse.setToken(tokenInfo.getTokenValue());
        return loginResponse;
    }

    @Override
    public LoginResponse phoneLogin(LoginMobileRequest loginRequest, HttpServletRequest request) {
        //检测验证码
        checkValidateCode(loginRequest.getPhone(), loginRequest.getCaptcha());
        //查询手机号信息
        User user = userService.getByPhone(loginRequest.getPhone());
        // 此用户不存在，走新用户注册流程
        if (ObjectUtil.isNull(user)) {
            user = userService.registerPhone(loginRequest.getPhone(),request);
        } else {
            if (!user.getStatus()) {
                throw new AsmrException("当前账户已禁用，请联系管理员！");
            }
            // 记录最后一次登录时间 & Ip
            user.setLastLoginTime(DateUtil.nowDateTime());
            user.setLastIp(AsmrUtil.getClientIp(request));
            boolean b = userService.updateById(user);
            if (!b) {
                log.error("用户登录时，记录最后一次登录时间出错,uid = {}", user.getUid());
            }
        }
        //生成token
        LoginResponse loginResponse = new LoginResponse();
        StpUtil.login(user.getUid());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        loginResponse.setToken(tokenInfo.getTokenValue());
        loginResponse.setUid(user.getUid());
        loginResponse.setNikeName(user.getNickname());
        loginResponse.setPhone(user.getPhone());
        return loginResponse;
    }

    @Override
    public Boolean register(LoginRequest loginRequest, HttpServletRequest request) {
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getAccount, loginRequest.getAccount());
        long count = userService.count(userQueryWrapper);
        if (count > 0) {
            throw new AsmrException("账号已存在");
        }
        String password = SercretUtil.encryptPassword(loginRequest.getPwd(), loginRequest.getAccount());
        User user = new User();
        user.setAccount(loginRequest.getAccount());
        user.setPwd(password);
        user.setNickname("游客"+ RandomUtil.randomNumbers(4));
        user.setStatus(false);
        return userService.save(user);
    }

    @Override
    public UserVo getUserInfo() {
        Object loginId = StpUtil.getLoginId();
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUid, loginId));
        return BeanUtil.copyProperties(user, UserVo.class);
    }

    private void checkValidateCode( String phone, String code) {
        Object validateCode = redisTemplate.opsForValue().get(SmsConstants.SMS_VALIDATE_PHONE + phone);
        if (ObjectUtil.isNull(validateCode)) {
            throw new AsmrException("验证码已过期");
        }
        if (!validateCode.toString().equals(code)) {
            throw new AsmrException("验证码错误");
        }
        //删除验证码
        redisTemplate.delete(SmsConstants.SMS_VALIDATE_PHONE + phone);
    }
}
